﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Net;
using System.Diagnostics;
namespace Spacer
{
	public static class Network
	{
        public static NetworkSession CurrentSession { get; set; }
		private static PacketReader packetReader;
		private static PacketWriter packetWriter;

        private const NetworkSessionType NETWORK_TYPE = NetworkSessionType.SystemLink;

		public static void Initialize()
		{
			packetReader = new PacketReader();
			packetWriter = new PacketWriter();
		}

		public static AvailableNetworkSessionCollection FindSessions()
		{
            try
            {
                AvailableNetworkSessionCollection availableSessions = NetworkSession.Find(NETWORK_TYPE, 1, null);
                if (availableSessions.Count == 0)
                {
                    Console.WriteLine("No network sessions found.");
                    return null;
                }
                return availableSessions;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                return null;
            }
		}

		public static void JoinSession(AvailableNetworkSession existingNetwork)
		{
			try
			{
				CurrentSession = NetworkSession.Join(existingNetwork);

				HookSessionEvents();
			}
			catch (Exception e)
			{
				Console.WriteLine(e.Message);
			}
		}

		public static void CreateSession(/*int maxGamers*/)
		{
			int maxGamers = 8;

			try
			{
                CurrentSession = NetworkSession.Create(NETWORK_TYPE, 1, maxGamers);
				CurrentSession.StartGame();
				if (CurrentSession != null)
				{
					CurrentSession.AllowJoinInProgress = true;
					CurrentSession.AllowHostMigration = false;

					HookSessionEvents();
                    Debug.WriteLine("SUCCESS!");
				}
			}
			catch (Exception e)
			{
				Console.WriteLine(e.Message);
			}
		}

		public static void DestroySession()
		{
			if( CurrentSession != null ) {
				CurrentSession.EndGame();
				CurrentSession.Dispose();
				CurrentSession = null;
			}
		}

		private static void HookSessionEvents()
		{
			CurrentSession.GamerJoined += GamerJoinedEventHandler;
			CurrentSession.GamerLeft += GamerLeftEventHandler;
			CurrentSession.SessionEnded += SessionEndedEventHandler;
		}

		private static void GamerJoinedEventHandler(object sender, GamerJoinedEventArgs e)
		{
            Globals.CurrentSession.OnPlayerJoin(e.Gamer);

            if (CurrentSession.IsHost)
            {
                Packet packet = new Packet("GalaxyData", Globals.CurrentSession.Galaxy);
                packetWriter.Write(packet.Serialize());

                CurrentSession.LocalGamers[0].SendData(packetWriter, SendDataOptions.ReliableInOrder);
            }
		}

		private static void GamerLeftEventHandler(object sender, GamerLeftEventArgs e)
		{
			Globals.CurrentSession.OnPlayerLeave( e.Gamer );
		}

		private static void SessionEndedEventHandler(object sender, NetworkSessionEndedEventArgs e)
		{
			Console.WriteLine(e.EndReason.ToString());

			CurrentSession.Dispose();
			CurrentSession = null;
		}

		public static void Update()
		{
			if (CurrentSession != null)
			{
				// Pump the underlying session object.
				CurrentSession.Update();
			}

			// Make sure the session has not ended.
			if (CurrentSession == null)
				return;

            SendPackets(CurrentSession.LocalGamers[0]);
			ReadPackets(CurrentSession.LocalGamers[0]);
			 
		}

        public static void WritePackets(Packet newPacket)
        {
            packetWriter.Write(newPacket.Serialize());
        }


        public static void SendPackets(LocalNetworkGamer gamer)
		{
			//gamer.SendData(packetWriter, SendDataOptions.Reliable);
		}


		public static void ReadPackets(LocalNetworkGamer gamer)
		{
			// Keep reading as long as incoming packets are available.
			while (gamer.IsDataAvailable)
			{
				NetworkGamer sender;

				// Read a single packet from the network.
				gamer.ReceiveData(packetReader, out sender);

				// Discard packets sent by local gamers: we already know their state!
				if (sender.IsLocal)
					continue;

                while (packetReader.Length > 0)
                {
                    Packet packet = Packet.Deserialize(packetReader.ReadString());

                    if (packet.Name == "GalaxyData")
                    {
                        Galaxy galaxy = (Galaxy)packet.Data;
                        galaxy.PostLoad();

                        Globals.PushActivity(Globals.CurrentSession = new GalaxySession(galaxy));
                    }
                }
			}
		}
	}
}
